import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/io.dart';

import '../app_logger.dart';
import 'smart_server_config.dart';
import '../constants/language_list.dart';

class DetectMode {
  static const int auto = 1;     // 自动检测语言（探测语言的范围是from和to）
  static const int fixed = 2;    // 指定语言from to
}

/// Microsoft WebSocket 翻译服务
///
/// 支持 BCP-47 标准语言代码的实时语音翻译服务
///
/// 主要功能：
/// - 实时语音识别 (ASR)
/// - 文本翻译 (TS)
/// - 语音合成 (TTS)
/// - 自动语言检测
/// - 固定语言对翻译
///
/// 使用示例：
/// ```dart
/// final service = MSWebSocketTransService();
///
/// // 连接服务器
/// await service.connect();
///
/// // 固定语言翻译：中文 -> 英文
/// await service.startFixedLanguageTranslation(
///   from: LanguageCodes.zhCN,
///   to: LanguageCodes.enUS,
/// );
///
/// // 自动语言检测
/// await service.startAutoDetectTranslation(
///   candidateLanguage1: LanguageCodes.zhCN,
///   candidateLanguage2: LanguageCodes.enUS,
/// );
/// ```
class MSWebSocketTransService {
  String _serverUrl = '';

  WebSocketChannel? _channel;
  StreamSubscription? _subscription;
  bool _isConnected = false;
  String? _currentSeq;

  // 回调函数
  Function(String text, String asrSid, bool isLast)? onAsrUpdate;
  Function(String text, String asrSid, String sourceLanguage, String targetLanguage)? onTranslation;
  Function(String audioUrl, String asrSid)? onTtsAudio;
  Function(String error)? onError;
  Function()? onConnected;
  Function()? onDisconnected;
  Function(String message)? onSessionEnded;

  // 语言设置 - 使用BCP-47标准语言代码
  String fromLanguage = LanguageCodes.zhCN; // 中文(简体，中国大陆)
  String toLanguage = LanguageCodes.enUS;   // 英文(美国)

  bool get isConnected => _isConnected;

  /// 连接WebSocket服务器
  Future<void> connect() async {
    if (_isConnected) return;

    try {
      // 使用SmartServerConfig获取推荐的服务器
      if (_serverUrl.isEmpty) {
        await SmartServerConfig.instance.initialize();
        final recommendedServer = await SmartServerConfig.instance.getRecommendedServer();
        _serverUrl = recommendedServer.url;
        log.d('🚀 使用智能推荐服务器: ${recommendedServer.name}');
      }

      log.d('🔌 正在连接WebSocket服务器: $_serverUrl');

      _channel = IOWebSocketChannel.connect(Uri.parse(_serverUrl));

      // 监听消息
      _subscription = _channel!.stream.listen(
        _handleMessage,
        onError: (error) {
          log.d('❌ WebSocket错误: $error');
          onError?.call('WebSocket连接错误: $error');
          _handleDisconnection();
        },
        onDone: () {
          log.d('🔌 WebSocket连接已关闭');
          _handleDisconnection();
        },
      );

      _isConnected = true;
      onConnected?.call();
      log.d('✅ WebSocket连接成功');

    } catch (e) {
      log.d('❌ WebSocket连接失败: $e');
      onError?.call('连接失败: $e');
      _handleDisconnection();
    }
  }

  /// 断开连接
  Future<void> disconnect() async {
    if (!_isConnected) return;

    try {
      // 发送结束报文
      if (_currentSeq != null) {
        await _sendEndMessage();
      }

      await _subscription?.cancel();
      await _channel?.sink.close();

      _handleDisconnection();
      log.d('🔌 WebSocket连接已断开');

    } catch (e) {
      log.d('❌ 断开连接时出错: $e');
      _handleDisconnection();
    }
  }

  /// 处理连接断开
  void _handleDisconnection() {
    _isConnected = false;
    _channel = null;
    _subscription = null;
    _currentSeq = null;
    onDisconnected?.call();
  }

  /// 开始翻译会话
  ///
  /// [from] 源语言的 BCP-47 代码，如 'zh-CN'、'en-US'
  /// [to] 目标语言的 BCP-47 代码
  /// [tsEnable] 是否启用文本翻译
  /// [ttsEnable] 是否启用语音合成
  /// [ttsFormat] TTS 音频格式，默认 'mp3'
  /// [asrFormat] ASR 音频格式，默认 'pcm'
  /// [ttsGender] TTS 语音性别，'male' 或 'female'
  /// [detectMode] 语言检测模式：1=自动检测，2=固定语言
  Future<void> startTranslation({
    String? from,
    String? to,
    bool tsEnable = true,
    bool ttsEnable = true,
    String ttsFormat = 'mp3',
    String asrFormat = 'pcm',
    String ttsGender = 'female',
    int detectMode = 2,
  }) async {
    if (!_isConnected) {
      throw Exception('WebSocket未连接');
    }

    // 更新语言设置
    if (from != null) fromLanguage = from;
    if (to != null) toLanguage = to;

    // 生成序列号
    _currentSeq = _generateSequence();

    final startMessage = {
      'businessType': 'ENTITY_TRANS',
      'auto': 1,
      'to': toLanguage,
      'detectMode': detectMode,
      'mockType': 1,
      'sound': 2,
      'tsEnable': tsEnable ? 1 : 0,
      'action': 'SATS',
      'from': fromLanguage,
      'flag': 'start',
      'ttsFormat': ttsFormat,
      'ttsEnable': ttsEnable ? 1 : 0,
      'ttsGender': ttsGender,
      'seq': _currentSeq,
      'asrFormat': asrFormat,
      'flow': 1,
    };

    try {
      _channel!.sink.add(jsonEncode(startMessage));
      log.d('📤 发送开始报文: from=$fromLanguage, to=$toLanguage');
    } catch (e) {
      log.d('❌ 发送开始报文失败: $e');
      onError?.call('发送开始报文失败: $e');
    }
  }

  /// 发送音频数据
  Future<void> sendAudioData(Uint8List audioData) async {
    if (!_isConnected || _currentSeq == null) {
      log.d('⚠️ WebSocket未连接或会话未开始，跳过音频数据发送');
      return;
    }

    try {
      _channel!.sink.add(audioData);
      log.d('📤 发送音频数据: ${audioData.length} bytes');
    } catch (e) {
      log.d('❌ 发送音频数据失败: $e');
      onError?.call('发送音频数据失败: $e');
    }
  }

  /// 结束翻译会话
  Future<void> endTranslation() async {
    if (!_isConnected || _currentSeq == null) return;

    await _sendEndMessage();
  }

  /// 发送结束报文
  Future<void> _sendEndMessage() async {
    if (_currentSeq == null) return;

    final endMessage = {
      'seq': _currentSeq,
      'action': 'SATS',
      'ttsFormat': 'mp3',
      'flag': 'end',
    };

    try {
      _channel!.sink.add(jsonEncode(endMessage));
      log.d('📤 发送结束报文');
      _currentSeq = null;
    } catch (e) {
      log.d('❌ 发送结束报文失败: $e');
    }
  }

  /// 处理服务器消息
  void _handleMessage(dynamic data) {
    try {
      if (data is String) {
        final message = jsonDecode(data) as Map<String, dynamic>;
        _processServerMessage(message);
      } else {
        log.d('⚠️ 收到非文本消息，忽略');
      }
    } catch (e) {
      log.d('❌ 处理服务器消息失败: $e');
      onError?.call('处理服务器消息失败: $e');
    }
  }

  /// 处理服务器响应消息
  void _processServerMessage(Map<String, dynamic> message) {
    final step = message['step'] as String?;
    final code = message['code'] as int?;
    final asrSid = message['asrSid'] as String?;

    // 处理结束会话响应 (code: 2025)
    if (code == 2025) {
      final msg = message['msg'] ?? '会话结束';
      log.d('✅ 服务器确认会话结束: $msg');
      // 清理当前序列号
      _currentSeq = null;
      // 通知上层应用会话已结束
      onSessionEnded?.call(msg);
      return;
    }

    if (code != 0) {
      final errorMsg = message['msg'] ?? '未知错误';
      log.d('❌ 服务器错误: $errorMsg (code: $code)');
      onError?.call('服务器错误: $errorMsg');
      return;
    }

    switch (step) {
      case 'ASR':
        _handleAsrResponse(message);
        break;
      case 'TS':
        _handleTranslationResponse(message);
        break;
      case 'TTS':
        _handleTtsResponse(message);
        break;
      default:
        log.d('⚠️ 未知步骤: $step');
    }
  }

  /// 处理ASR响应
  void _handleAsrResponse(Map<String, dynamic> message) {
    final text = message['text'] as String?;
    final asrSid = message['asrSid'] as String?;
    final isLast = message['isLast'] as bool?;

    if (text != null && asrSid != null) {
      log.d('🎤 ASR识别: $text (isLast: $isLast)');
      onAsrUpdate?.call(text, asrSid, isLast ?? false);
    }
  }

  /// 处理翻译响应
  void _handleTranslationResponse(Map<String, dynamic> message) {
    final text = message['text'] as String?;
    final asrSid = message['asrSid'] as String?;
    final sourceLanguage = message['from'] as String?;
    final targetLanguage = message['to'] as String?;

    log.d('🔤 翻译结果: text: $text , sourceLanguage: $sourceLanguage , targetLanguage: $targetLanguage');

    if (text != null && asrSid != null) {
      log.d('🔤 翻译结果: $text');
      onTranslation?.call(text, asrSid, sourceLanguage ?? '', targetLanguage ?? '');
    }
  }

  /// 处理TTS响应
  void _handleTtsResponse(Map<String, dynamic> message) {
    final url = message['url'] as String?;
    final asrSid = message['asrSid'] as String?;

    if (url != null && asrSid != null) {
      log.d('🔊 TTS音频: $url');
      onTtsAudio?.call(url, asrSid);
    }
  }

  /// 生成序列号
  String _generateSequence() {
    final random = Random();
    final randomStr = List.generate(32, (index) =>
        random.nextInt(16).toRadixString(16).toUpperCase()).join('');
    final timestamp = DateTime.now().millisecondsSinceEpoch;

    return '$fromLanguage|$toLanguage|$randomStr|$timestamp';
  }

  /// 设置语言
  void setLanguages({required String from, required String to}) {
    fromLanguage = from;
    toLanguage = to;
    log.d('🌐 语言设置: from=$from, to=$to');
  }

  /// 获取连接状态信息
  Map<String, dynamic> getStatus() {
    return {
      'connected': _isConnected,
      'currentSeq': _currentSeq,
      'fromLanguage': fromLanguage,
      'toLanguage': toLanguage,
      'serverUrl': _serverUrl,
    };
  }

  /// 获取当前服务器URL
  String getServerUrl() {
    return _serverUrl;
  }

  /// 获取当前服务器名称
  String getServerName() {
    return SmartServerConfig.getServerName(_serverUrl);
  }

  /// 使用自动检测模式开始翻译
  ///
  /// 系统将在提供的两种候选语言之间自动检测输入的语言
  ///
  /// [candidateLanguage1] 候选语言1的 BCP-47 代码
  /// [candidateLanguage2] 候选语言2的 BCP-47 代码
  /// [tsEnable] 是否启用文本翻译
  /// [ttsEnable] 是否启用语音合成
  /// [ttsFormat] TTS 音频格式，默认 'mp3'
  /// [asrFormat] ASR 音频格式，默认 'pcm'
  /// [ttsGender] TTS 语音性别，'male' 或 'female'
  Future<void> startAutoDetectTranslation({
    required String candidateLanguage1,
    required String candidateLanguage2,
    bool tsEnable = true,
    bool ttsEnable = true,
    String ttsFormat = 'mp3',
    String asrFormat = 'pcm',
    String ttsGender = 'female',
  }) async {
    await startTranslation(
      from: candidateLanguage1,
      to: candidateLanguage2,
      detectMode: DetectMode.auto,
      tsEnable: tsEnable,
      ttsEnable: ttsEnable,
      ttsFormat: ttsFormat,
      asrFormat: asrFormat,
      ttsGender: ttsGender,
    );
  }

  /// 使用固定语言模式开始翻译
  ///
  /// 指定明确的源语言和目标语言进行翻译
  ///
  /// [from] 源语言的 BCP-47 代码，如 'zh-CN'
  /// [to] 目标语言的 BCP-47 代码，如 'en-US'
  /// [tsEnable] 是否启用文本翻译
  /// [ttsEnable] 是否启用语音合成
  /// [ttsFormat] TTS 音频格式，默认 'mp3'
  /// [asrFormat] ASR 音频格式，默认 'pcm'
  /// [ttsGender] TTS 语音性别，'male' 或 'female'
  Future<void> startFixedLanguageTranslation({
    required String from,
    required String to,
    bool tsEnable = true,
    bool ttsEnable = true,
    String ttsFormat = 'mp3',
    String asrFormat = 'pcm',
    String ttsGender = 'female',
  }) async {
    await startTranslation(
      from: from,
      to: to,
      detectMode: DetectMode.fixed,
      tsEnable: tsEnable,
      ttsEnable: ttsEnable,
      ttsFormat: ttsFormat,
      asrFormat: asrFormat,
      ttsGender: ttsGender,
    );
  }

  /// 清理资源
  void dispose() {
    disconnect();
  }
}